package com.lsh.oms.core.proxy.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.oms.api.model.es.OrderHeadForEs;
import com.lsh.oms.api.model.order.create.MisOrderHeadDTO;
import com.lsh.oms.api.service.es.EsAsyncInterface;
import com.lsh.oms.api.service.es.EsSyncInterface;
import com.lsh.oms.core.constant.Constants;
import com.lsh.oms.core.enums.AbstractTaskType;
import com.lsh.oms.core.enums.YN;
import com.lsh.oms.core.model.order.OrderHead;
import com.lsh.oms.core.model.order.OrderHeadExt;
import com.lsh.oms.core.proxy.AbstractAsyncTask;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author panxudong
 * @date 16/12/23
 */
@Component
public class EsProxy {

    private static Logger logger = LoggerFactory.getLogger(EsProxy.class);

    @Autowired
    private EsAsyncInterface esAsyncInterface;

    @Autowired
    private EsSyncInterface esSyncInterface;


    public static OrderHeadForEs transformToOrderHeadForEs(OrderHead orderHead, MisOrderHeadDTO misOrderHeadDTO) {

        JSONObject json = new JSONObject();
        json.put("marketName", misOrderHeadDTO.getMarketName());
        json.put("adminName", misOrderHeadDTO.getAdminName());
        json.put("username", misOrderHeadDTO.getUsername());

        return transformToOrderHeadForEs(orderHead, json, misOrderHeadDTO.getDcCode());
    }


    public static OrderHeadForEs transformToOrderHeadForEs(OrderHead orderHead, Boolean flag) {

        JSONObject json = new JSONObject();
        JSONObject ext = JSON.parseObject(orderHead.getExt());;
        json.put("marketName", ext.getString("marketName"));
        json.put("adminName", ext.getString("adminName"));
        json.put("username", ext.getString("username"));

        String orderDc = ext.getString("orderDc");
//        String orderDc = "";
//        if (null != orderDcOb) {
//            orderDc = (String) orderDcOb;
//        }

        return transformToOrderHeadForEsALL(orderHead, json, orderDc);
    }


    private static OrderHeadForEs transformToOrderHeadForEs(OrderHead orderHead, JSONObject json, String orderDc) {
        OrderHeadForEs orderHeadForEs = new OrderHeadForEs();

        orderHeadForEs.setPayType(orderHead.getPayType());
        orderHeadForEs.setOrderCode(orderHead.getOrderCode());
        orderHeadForEs.setParentOrderCode(orderHead.getParentOrderCode());
        orderHeadForEs.setRegionCode(orderHead.getRegionCode());
        orderHeadForEs.setOrderStatus(orderHead.getOrderStatus());
        orderHeadForEs.setLackDeliveryType(orderHead.getLackDeliveryType());
        orderHeadForEs.setStorageType(orderHead.getStorageType());
        orderHeadForEs.setOrderTime(orderHead.getOrderTime());
        orderHeadForEs.setUserCode(orderHead.getUserCode());
        orderHeadForEs.setAddressCode(orderHead.getAddressCode());
        orderHeadForEs.setExpectPayAmount(orderHead.getExpectPayAmount());

        orderHeadForEs.setVenderId(orderHead.getVenderId());

        orderHeadForEs.setOrderDc(orderDc);

        JSONObject addressJson = JSON.parseObject(orderHead.getAddressInfo());
        String dmallOrderId = addressJson.getString("DuoDianOrderId");
        if (StringUtils.isNoneBlank(dmallOrderId)) {
            orderHeadForEs.setDmallOrderId(dmallOrderId);
        } else {
            orderHeadForEs.setDmallOrderId("0");
        }

        String marketName = ObjectUtils.toString(json.get("marketName"));
        String adminName = ObjectUtils.toString(json.get("adminName"));
        String username = ObjectUtils.toString(json.get("username"));

        if (StringUtils.isAnyBlank(marketName, adminName, username)) {
            String ext = orderHead.getExt();
            if (StringUtils.isNotBlank(ext)) {
                JSONObject extJson = JSON.parseObject(ext);

                marketName = extJson.getString("marketName");
                adminName = extJson.getString("adminName");
                username = extJson.getString("username");
            }
        }

        orderHeadForEs.setMarketName(marketName);
        orderHeadForEs.setAdminName(adminName);
        orderHeadForEs.setUsername(username);
        orderHeadForEs.setAftersalesStatus(YN.N.getValue());

        String headExt = orderHead.getExt();
        if (StringUtils.isNoneBlank(headExt)) {
            JSONObject extJson = JSONObject.parseObject(headExt);

            orderHeadForEs.setProviderId(extJson.getString("providerId"));
        }

        OrderHeadExt orderHeadExt = orderHead.getExtObject();
        String ext = orderHeadExt.getExt();

        if (StringUtils.isNotBlank(ext)) {
            JSONObject extJson = JSONObject.parseObject(ext);

            logger.info("orderCode-" + orderHeadForEs.getOrderCode() + ",ext is " + extJson);

            String userType = extJson.getString("user_type");
            if (StringUtils.isNotBlank(userType)) {
                orderHeadForEs.setUserType(Integer.parseInt(userType));
            } else {
                logger.info("orderCode-{}-addressInfo is " + orderHead.getAddressInfo(), orderHead.getOrderCode());
                orderHeadForEs.setUserType(getUserType(orderHead.getAddressInfo()));
            }

            String memberLevel = extJson.getString("member_level");
            if (StringUtils.isNotBlank(memberLevel)) {
                orderHeadForEs.setMemberLevel(Integer.parseInt(memberLevel));
            }
        }

        return orderHeadForEs;
    }

    private static OrderHeadForEs transformToOrderHeadForEsALL(OrderHead orderHead, JSONObject json, String orderDc) {
        OrderHeadForEs orderHeadForEs = new OrderHeadForEs();

        orderHeadForEs.setPayType(orderHead.getPayType());
        orderHeadForEs.setOrderCode(orderHead.getOrderCode());
        orderHeadForEs.setParentOrderCode(orderHead.getParentOrderCode());
        orderHeadForEs.setRegionCode(orderHead.getRegionCode());
        orderHeadForEs.setOrderStatus(orderHead.getOrderStatus());
        orderHeadForEs.setLackDeliveryType(orderHead.getLackDeliveryType());
        orderHeadForEs.setStorageType(orderHead.getStorageType());
        orderHeadForEs.setOrderTime(orderHead.getOrderTime());
        orderHeadForEs.setUserCode(orderHead.getUserCode());
        orderHeadForEs.setAddressCode(orderHead.getAddressCode());
        orderHeadForEs.setExpectPayAmount(orderHead.getExpectPayAmount());

        orderHeadForEs.setVenderId(orderHead.getVenderId());

        orderHeadForEs.setOrderDc(orderDc);

        JSONObject addressJson = JSON.parseObject(orderHead.getAddressInfo());
        String dmallOrderId = addressJson.getString("DuoDianOrderId");
        if (StringUtils.isNoneBlank(dmallOrderId)) {
            orderHeadForEs.setDmallOrderId(dmallOrderId);
        } else {
            orderHeadForEs.setDmallOrderId("0");
        }

        String marketName = ObjectUtils.toString(json.get("marketName"));
        String adminName = ObjectUtils.toString(json.get("adminName"));
        String username = ObjectUtils.toString(json.get("username"));

        if (StringUtils.isAnyBlank(marketName, adminName, username)) {
            String ext = orderHead.getExt();
            if (StringUtils.isNotBlank(ext)) {
                JSONObject extJson = JSON.parseObject(ext);

                marketName = extJson.getString("marketName");
                adminName = extJson.getString("adminName");
                username = extJson.getString("username");
            }
        }

        orderHeadForEs.setMarketName(marketName);
        orderHeadForEs.setAdminName(adminName);
        orderHeadForEs.setUsername(username);
        orderHeadForEs.setAftersalesStatus(YN.N.getValue());



        String headExt = orderHead.getExt();
        if (StringUtils.isNoneBlank(headExt)) {
            JSONObject extJson = JSONObject.parseObject(headExt);

            orderHeadForEs.setProviderId(extJson.getString("providerId"));

            orderHeadForEs.setWarehouseCode(extJson.getString("warehouse_code"));
        }

        orderHeadForEs.setUserType(getUserType(orderHead.getAddressInfo()));

//        OrderHeadExt orderHeadExt = orderHead.getExtObject();
//        String ext = orderHeadExt.getExt();
//
//        if (StringUtils.isNotBlank(ext)) {
//            JSONObject extJson = JSONObject.parseObject(ext);
//
//            logger.info("orderCode-" + orderHeadForEs.getOrderCode() + ",ext is " + extJson);
//
//            String userType = extJson.getString("user_type");
//            if (StringUtils.isNotBlank(userType)) {
//                orderHeadForEs.setUserType(Integer.parseInt(userType));
//            } else {
//                logger.info("orderCode-{}-addressInfo is " + orderHead.getAddressInfo(), orderHead.getOrderCode());
//
//            }
//
//            String memberLevel = extJson.getString("member_level");
//            if (StringUtils.isNotBlank(memberLevel)) {
//                orderHeadForEs.setMemberLevel(Integer.parseInt(memberLevel));
//            }
//        }

        return orderHeadForEs;
    }

    /**
     * @param addressInfo
     * @return
     */
    private static int getUserType(String addressInfo) {
        if (StringUtils.isNotBlank(addressInfo)) {
            JSONObject addressInfoJson = JSON.parseObject(addressInfo);

            String userType = addressInfoJson.getString("user_type");
            if (StringUtils.isNotBlank(userType)) {
                return Integer.parseInt(userType);
            }
        }

        return 1;
    }

    public static OrderHeadForEs transformToOrderHeadForEs(OrderHead orderHead) {
        OrderHeadForEs orderHeadForEs = new OrderHeadForEs();

        orderHeadForEs.setOrderCode(orderHead.getOrderCode());
        orderHeadForEs.setOrderStatus(orderHead.getOrderStatus());
        orderHeadForEs.setLackDeliveryType(orderHead.getLackDeliveryType());
        orderHeadForEs.setSoCodes(orderHead.getSoCodes());

        if (StringUtils.isNotBlank(orderHead.getExt())) {
            JSONObject extObject = JSONObject.parseObject(orderHead.getExt());
            orderHeadForEs.setWarehouseCode(extObject.getString(Constants.WAREHOUSE_CODE));
            orderHeadForEs.setIsDelayPayment(extObject.getInteger(Constants.IS_DELAY_PAYMENT));
            orderHeadForEs.setIsPay(extObject.getInteger(Constants.IS_PAY));
        }

        return orderHeadForEs;
    }

    public static OrderHeadForEs transformToOrderHeadForEs(OrderHead orderHead, OrderHeadExt orderHeadExt) {
        OrderHeadForEs orderHeadForEs = new OrderHeadForEs();

        orderHeadForEs.setOrderCode(orderHead.getOrderCode());
        orderHeadForEs.setOrderStatus(orderHead.getOrderStatus());
        orderHeadForEs.setIsComment(orderHeadExt.getIsComment());

        return orderHeadForEs;
    }

    public static OrderHeadForEs transformToOrderHeadForEs(Long orderCode, Integer aftersalesStatus) {
        OrderHeadForEs orderHeadForEs = new OrderHeadForEs();

        orderHeadForEs.setOrderCode(orderCode);
        orderHeadForEs.setAftersalesStatus(aftersalesStatus);

        return orderHeadForEs;
    }

    public <T> EsProxy.EsTask newAsyncCreateTask(T index, String logSign) {
        return new EsTask(new EsDto(index), logSign, EsOperateType.CREATE);
    }

    public <T> EsProxy.EsTask newAsyncEditTask(T index, String logSign) {
        return new EsTask(new EsDto(index), logSign, EsOperateType.EDIT);
    }

    public <T> EsProxy.EsTask asyncDeleteIndexTask(T index, String logSign) {
        return new EsTask(new EsDto(index), logSign, EsOperateType.DELETE);
    }

    public <T> boolean deleteIndex(T index, String logSign) {
        this.execute(new EsDto(index), logSign, EsOperateType.DELETE);
        return true;
    }

    public <T> boolean createIndex(T index, String logSign) {
        this.execute(new EsDto(index), logSign, EsOperateType.CREATE);
        return true;
    }

    public <T> boolean editIndex(T index, String logSign) {
        this.execute(new EsDto(index), logSign, EsOperateType.EDIT);
        return true;
    }

    public <T> boolean batchEditIndex(List<T> indexList, String logSign) {
        this.execute(new EsDto(indexList), logSign, EsOperateType.BATCH_EDIT);
        return true;
    }

    public String selectIndex(String query, Boolean isCount) {
        return this.esSyncInterface.selectIndex(query, isCount);
    }

    private <T> boolean execute(EsDto esDto, String logSign, EsOperateType operateType) {
        String msg = " [" + operateType.getDesc() + " index][" + logSign + "]";
        logger.info(msg + "[start][Params:" + esDto.toJson());
        try {
            if (operateType == EsOperateType.CREATE) {
                esAsyncInterface.createIndex(esDto.getIndex());
            } else if (operateType == EsOperateType.EDIT) {
                esAsyncInterface.editIndex(esDto.getIndex());
            } else if (operateType == EsOperateType.BATCH_EDIT) {
                esAsyncInterface.batchEditIndex(esDto.getIndexList());
            } else if (operateType == EsOperateType.DELETE) {
                esAsyncInterface.deleteIndex(esDto.getIndex());
            }
            logger.info(msg + "[success]");
        } catch (Exception e) {
            logger.error(msg + "[error]" + "[Error Class : " + e.getClass() + ", Error Message : " + e.getMessage() + "]");
            logger.error(e.getMessage(), e);
            return false;
        }

        return true;
    }

    /**
     *
     */
    enum EsOperateType {
        CREATE(1, "Create"),
        EDIT(2, "Edit"),
        BATCH_EDIT(3, "Batch edit"),
        DELETE(4, "Delete");

        private int index;
        private String desc;

        EsOperateType(int index, String desc) {
            this.index = index;
            this.desc = desc;
        }

        public int getIndex() {
            return index;
        }

        public String getDesc() {
            return desc;
        }
    }

    /**
     *
     */
    class EsTask extends AbstractAsyncTask {
        private EsDto esDto;
        private String logSign;
        private EsOperateType esOperateType;

        public EsTask(final EsDto esDto, final String logSign, final EsOperateType esOperateType) {
            super(AbstractTaskType.ES_TASK);
            this.esDto = esDto;
            this.logSign = logSign;
            this.esOperateType = esOperateType;
        }

        @Override
        public void execute() {
            EsProxy.this.execute(esDto, logSign, esOperateType);
        }
    }

    private class EsDto<T> {
        private T index;
        private List<T> indexList;

        public EsDto(T index) {
            this.index = index;
        }

        public EsDto(List<T> indexList) {
            this.indexList = indexList;
        }

        public T getIndex() {
            return index;
        }

        public List<T> getIndexList() {
            return indexList;
        }

        public String toJson() {
            if (index != null) {
                return JSON.toJSONString(index);
            }
            if (indexList != null) {
                return JSON.toJSONString(indexList);
            }
            return null;
        }
    }

}